package dk.itu.samd.group2.tagapastry;

import java.io.IOException;
import java.util.ConcurrentModificationException;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;

import rice.p2p.commonapi.Endpoint;
import rice.p2p.commonapi.rawserialization.InputBuffer;
import rice.p2p.commonapi.rawserialization.OutputBuffer;

/*
 * This class encapsulates all the data that need to be exchanged
 * during leaf set maintenance
 */
public class NodeState {
	
	private Hashtable<Tag,Index> indexes;
	private int retractionThreshold, 
				expansionThreshold;
	
	public NodeState(Hashtable<Tag,Index> leafIndexes, int ret, int exp)
	{
		this.indexes = leafIndexes;
		this.retractionThreshold = ret;
		this.expansionThreshold = exp;
	}
	
	/*
	 * Used for deserialization, once message arrives
	 */
	public NodeState(InputBuffer buf, Endpoint endpoint) throws IOException {
		this.retractionThreshold = buf.readInt();
		this.expansionThreshold = buf.readInt();
		
		int size = buf.readInt();
		this.indexes = new Hashtable<Tag, Index>(size);
		for(int i = 0; i < size; i++) {
			Tag tag = new Tag(buf, endpoint);
			Index idx = new IndexImpl(buf, endpoint);
			
			this.indexes.put(tag, idx);
		}
	}
	
	public int getSize() {
		int size = 8; // For ret and exp.
		
		try {
			Set<Tag> set = indexes.keySet();
			Tag[] tags = (Tag[])set.toArray(new Tag[set.size()]);
			for(int i=0; i < tags.length; i++) {
				size += tags[i].getSize();
				size += indexes.get(tags[i]).getIndexSize();
			}
		}catch(ConcurrentModificationException ex) {
			System.out.println("Puha in nodestate");
		}
		
		return size;
				
//		int index = 0;
//		do {
//			try {
//				for(Tag t : indexes.keySet())
//					size += t.getSize();
//				
//				
//				for(Index i : indexes.values()) {
//					size += i.getIndexSize();
//				}
//				return size;
//			}
//			catch(ConcurrentModificationException cce) {
//				index++;
//			}
//		}while(index < 10);
//		
//		return size;
	}
	
	/*
	 * This object will be part of a replication msg so needs
	 * to be able to serialize
	 */
	public void serialize(OutputBuffer buf) throws IOException {
		buf.writeInt(this.retractionThreshold);
		buf.writeInt(this.expansionThreshold);
		buf.writeInt(this.indexes.size());
		for(Tag t : indexes.keySet()) {
			t.serialize(buf);
			Index i = indexes.get(t);
			i.serialize(buf);
		}
	}
	
	/*
	 * Get indexes which are part of the node state
	 */
	public Hashtable<Tag, Index> getIndexes() {
		return this.indexes;
	}
}
